/***********************************************************************
 *            Project: CoreCms
 *        ProjectName: 核心内容管理系统                                
 *                Web: https://www.corecms.net                      
 *             Author: 大灰灰                                          
 *              Email: jianweie@163.com                                
 *         CreateTime: 2021/1/31 21:45:10
 *        Description: 暂无
 ***********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.DTO;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.Entities.Expression;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.DTO;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using NetTaste;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 促销表 接口实现
    /// </summary>
    public class CoreCmsPromotionServices : BaseServices<CoreCmsPromotion>, ICoreCmsPromotionServices
    {
        private readonly ICoreCmsPromotionRepository _dal;
        private readonly IUnitOfWork _unitOfWork;

        private readonly ICoreCmsPromotionConditionServices _promotionConditionServices;
        private readonly ICoreCmsPromotionResultServices _promotionResultServices;
        private readonly IServiceProvider _serviceProvider;

        private readonly ICoreCmsCouponServices _couponServices;


        public CoreCmsPromotionServices(IUnitOfWork unitOfWork
            , ICoreCmsPromotionRepository dal
            , ICoreCmsPromotionConditionServices promotionConditionServices
            , ICoreCmsPromotionResultServices promotionResultServices
            , IServiceProvider serviceProvider, ICoreCmsCouponServices couponServices)
        {
            this._dal = dal;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;

            _promotionConditionServices = promotionConditionServices;
            _promotionResultServices = promotionResultServices;
            _serviceProvider = serviceProvider;
            _couponServices = couponServices;
        }


        #region 购物车的数据传过来，然后去算促销================

        /// <summary>
        /// 购物车的数据传过来，然后去算促销
        /// </summary>
        /// <param name="cart"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<CartDto> ToPromotion(CartDto cart, int type = (int)GlobalEnumVars.PromotionType.Promotion)
        {
            //团购秒杀不会走到这里,团购秒杀直接调用setPromotion方法
            if (type == (int)GlobalEnumVars.PromotionType.Group || type == (int)GlobalEnumVars.PromotionType.Seckill)
            {
                return cart;
            }

            //按照权重取所有已生效的促销列表
            var dt = DateTime.Now;
            var promotions = await _dal.QueryListByClauseAsync(p => p.isEnable == true && p.startTime < dt && p.endTime > dt && p.type == (int)GlobalEnumVars.PromotionType.Promotion && p.isDel == false, p => p.sort, OrderByType.Asc);

            foreach (var item in promotions)
            {
                //如果当前这个条件满足，并且它排他（意思就是它可以了，别的就不要来了。）
                var isSatisfy = await SetPromotion(item, cart);
                if (item.isExclusive == true && isSatisfy) break;
            }

            return cart;
        }
        #endregion

        #region 购物车的数据传过来，然后去算优惠券

        /// <summary>
        /// 购物车的数据传过来，然后去算优惠券
        /// </summary>
        /// <param name="cart"></param>
        /// <param name="promotions"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> ToCoupon(CartDto cart, List<CoreCmsPromotion> promotions)
        {
            var jm = new WebApiCallBack();
            foreach (var item in promotions)
            {
                if (item == null)
                {
                    jm.data = 15014;
                    jm.msg = GlobalErrorCodeVars.Code15014;
                    return jm;
                }
                var bl = await SetPromotion(item, cart);
                if (bl)
                {
                    cart.coupon.Add(item.name);
                }
                else
                {
                    jm.data = 15014;
                    jm.msg = GlobalErrorCodeVars.Code15014;
                    return jm;
                }
            }
            jm.status = true;
            jm.data = cart;
            return jm;
        }

        #endregion

        #region 根据促销信息，去计算购物车的促销情况

        /// <summary>
        /// 根据促销信息，去计算购物车的促销情况
        /// </summary>
        /// <param name="promotion"></param>
        /// <param name="cartModel"></param>
        /// <returns></returns>
        public async Task<bool> SetPromotion(CoreCmsPromotion promotion, CartDto cartModel)
        {
            var promotionConditions = await _promotionConditionServices.QueryListByClauseAsync(p => p.promotionId == promotion.id);
            //循环取出所有的促销条件，有一条不满足，就不行，就返回false
            var key = true;
            foreach (var item in promotionConditions)
            {
                var res = await _promotionConditionServices.check(item, cartModel, promotion);
                if (!key) continue;
                if (!res)
                {
                    //多个促销条件中，如果有一个不满足，整体就不满足，但是为了显示完整的促销标签，还是要运算完所有的促销条件
                    key = false;
                }
            }
            if (key)
            {
                //走到这一步就说明所有的促销条件都符合，那么就去计算结果
                var promotionResults = await _promotionResultServices.QueryListByClauseAsync(p => p.promotionId == promotion.id, p => p.id, OrderByType.Asc, true, true);
                foreach (var item in promotionResults)
                {
                    await _promotionResultServices.toResult(item, cartModel, promotion);
                }
            }
            else
            {
                //如果不满足需求，就要统一标准，把有些满足条件的（2），变成1
                _promotionConditionServices.PromotionFalse(cartModel, promotion);
            }
            return key;
        }
        #endregion

        #region 获取团购列表数据（根据营销序列）
        /// <summary>
        /// 获取团购列表数据（根据营销序列）
        /// </summary>
        /// <returns></returns>
        public async Task<List<GroupPurchaseSeckillDTO>> GetGroupListForPages(int[] promotionIds)
        {
            using var container = _serviceProvider.CreateScope();

            var goodsServices = container.ServiceProvider.GetService<ICoreCmsGoodsServices>();

            var dtoData = new List<GroupPurchaseSeckillDTO>();

            var promotions = await _dal.QueryListByClauseAsync(p => p.isEnable == true && p.isDel == false && promotionIds.Contains(p.id), promotionIds.Length, p => p.id, OrderByType.Desc, true, true);
            if (promotions != null && promotions.Any())
            {
                //获取团购序列
                var pIds = promotions.Select(p => p.id).ToList();
                //获取规则参数
                var conditions = await _promotionConditionServices.QueryListByClauseAsync(p => pIds.Contains(p.promotionId), p => p.id, OrderByType.Asc, true, true);
                //获取规则结果集
                var results = await _promotionResultServices.QueryListByClauseAsync(p => pIds.Contains(p.promotionId), p => p.id, OrderByType.Asc, true, true);

                var goodIds = (from condition in conditions where condition != null && condition.parameters.Contains("goodsId") select (JObject)JsonConvert.DeserializeObject(condition.parameters) into parameters select parameters["goodsId"].ObjectToInt(0)).ToList();

                var goodData = await goodsServices.QueryGoodWithDefaultProductAsync(p => goodIds.Contains(p.id), p => p.id, OrderByType.Asc, true);

                foreach (var item in promotions)
                {
                    var dtNow = DateTime.Now;

                    var dto = new GroupPurchaseSeckillDTO();

                    //事物处理过程开始
                    dto.id = item.id;
                    dto.name = item.name;
                    dto.type = item.type;
                    dto.sort = item.sort;
                    dto.maxNums = item.maxNums;
                    dto.maxGoodsNums = item.maxGoodsNums;
                    dto.maxRecevieNums = item.maxRecevieNums;
                    dto.startTime = item.startTime;
                    dto.endTime = item.endTime;
                    dto.isEnable = item.isEnable;
                    dto.isExclusive = item.isExclusive;
                    dto.isAutoReceive = item.isAutoReceive;
                    dto.effectiveDays = item.effectiveDays;
                    dto.effectiveHours = item.effectiveHours;

                    var dt = DateTime.Now;
                    if (item.startTime > dt)
                    {
                        dto.startStatus = (int)GlobalEnumVars.GroupSeckillStatus.Upcoming;
                    }
                    else if (item.startTime < dt && dt < item.endTime)
                    {
                        dto.startStatus = (int)GlobalEnumVars.GroupSeckillStatus.InProgress;
                    }
                    else if (item.endTime < dt)
                    {
                        dto.startStatus = (int)GlobalEnumVars.GroupSeckillStatus.Finished;
                    }

                    var condition = conditions.Find(p => p.promotionId == item.id);
                    if (condition != null && condition.parameters.Contains("goodsId"))
                    {
                        var parameters = (JObject)JsonConvert.DeserializeObject(condition.parameters);
                        var goodId = parameters["goodsId"].ObjectToInt(0);
                        var good = goodData.Find(p => p.id == goodId);
                        if (good != null)
                        {
                            dto.goodBrief = good.brief;
                            dto.goodName = good.name;
                            dto.goodThumbnail = good.image;
                            dto.goodImages = good.images;
                            dto.goodStock = good.stock;
                            dto.goodViewCount = good.viewCount;
                            dto.goodUnit = good.unit;
                            dto.mktPrice = good.mktprice;
                            dto.price = good.price;

                            if (dto.startStatus == (int)GlobalEnumVars.GroupSeckillStatus.Upcoming)
                            {
                                var ts = item.startTime.Subtract(dtNow);
                                dto.timestamp = (int)ts.TotalSeconds;
                            }
                            else if (dto.startStatus == (int)GlobalEnumVars.GroupSeckillStatus.InProgress)
                            {
                                var ts = item.endTime.Subtract(dtNow);
                                dto.timestamp = (int)ts.TotalSeconds;
                            }
                            else if (dto.startStatus == (int)GlobalEnumVars.GroupSeckillStatus.Finished)
                            {
                                dto.timestamp = 0;
                            }
                        }
                    }
                    var result = results.Find(p => p.promotionId == item.id);
                    if (result != null)
                    {
                        var resultParameters = (JObject)JsonConvert.DeserializeObject(result.parameters);
                        decimal promotionAmount = 0;
                        {
                            var cartProducts = new CartProducts()
                            {
                                nums = 1,
                                products = new CoreCmsProducts()
                                {
                                    price = dto.price,
                                    amount = dto.price,
                                }
                            };
                            switch (result.code)
                            {
                                //指定商品减固定金额
                                case "GOODS_REDUCE":
                                    promotionAmount = _promotionResultServices.result_GOODS_REDUCE(resultParameters, cartProducts, item);
                                    break;
                                //指定商品打X折
                                case "GOODS_DISCOUNT":
                                    promotionAmount = _promotionResultServices.result_GOODS_DISCOUNT(resultParameters, cartProducts, item);
                                    break;
                                //指定商品一口价
                                case "GOODS_ONE_PRICE":
                                    promotionAmount = _promotionResultServices.result_GOODS_ONE_PRICE(resultParameters, cartProducts, item);
                                    break;
                                //指定商品每第几件减指定金额
                                case "GOODS_HALF_PRICE":
                                    //这个条件不在列表做处理
                                    promotionAmount = 0;
                                    break;
                            }
                        }
                        if (promotionAmount > 0)
                        {
                            dto.price = Math.Round(dto.price - promotionAmount, 2);
                        }
                    }
                    dtoData.Add(dto);
                }
            }
            return dtoData;
        }

        #endregion

        #region 获取团购列表数据（根据类型获取当前可用）
        /// <summary>
        /// 获取团购列表数据（根据类型获取当前可用）
        /// </summary>
        /// <returns></returns>
        public async Task<WebApiCallBack> GetGroupList(int type, int status, int pageIndex, int pageSize)
        {
            using var container = _serviceProvider.CreateScope();

            var goodsServices = container.ServiceProvider.GetService<ICoreCmsGoodsServices>();
            var orderServices = container.ServiceProvider.GetService<ICoreCmsOrderServices>();

            var jm = new WebApiCallBack { status = true };

            var where = PredicateBuilder.True<CoreCmsPromotion>();
            where = where.And(p => p.isEnable == true && p.isDel == false && p.type == type);

            var dt = DateTime.Now;

            if (status == (int)GlobalEnumVars.GroupSeckillStatus.Upcoming)
            {
                where = where.And(p => p.startTime > dt);

            }
            else if (status == (int)GlobalEnumVars.GroupSeckillStatus.InProgress)
            {
                where = where.And(p => p.startTime < dt && dt < p.endTime);
            }
            else if (status == (int)GlobalEnumVars.GroupSeckillStatus.Finished)
            {
                where = where.And(p => p.endTime < dt);
            }
            var goods = new List<CoreCmsGoods>();
            var promotions = await _dal.QueryPageAsync(where, p => p.endTime, OrderByType.Desc, pageIndex, pageSize, true, true, 60);
            var dtoData = new List<GroupPurchaseSeckillDTO>();
            if (promotions != null && promotions.Any())
            {
                //获取团购序列
                var pIds = promotions.Select(p => p.id).ToList();
                //获取规则参数
                var conditions = await _promotionConditionServices.QueryListByClauseAsync(p => pIds.Contains(p.promotionId), p => p.id, OrderByType.Asc, true, true);
                //获取规则结果集
                var results = await _promotionResultServices.QueryListByClauseAsync(p => pIds.Contains(p.promotionId), p => p.id, OrderByType.Asc, true, true);

                var goodIds = (from condition in conditions where condition != null && condition.parameters.Contains("goodsId") select (JObject)JsonConvert.DeserializeObject(condition.parameters) into parameters select parameters["goodsId"].ObjectToInt(0)).ToList();

                var goodData = await goodsServices.QueryGoodWithDefaultProductAsync(p => goodIds.Contains(p.id), p => p.id, OrderByType.Asc, true);

                foreach (var item in promotions)
                {
                    var dtNow = DateTime.Now;

                    var dto = new GroupPurchaseSeckillDTO();

                    //事物处理过程开始
                    dto.id = item.id;
                    dto.name = item.name;
                    dto.type = item.type;
                    dto.sort = item.sort;
                    dto.maxNums = item.maxNums;
                    dto.maxGoodsNums = item.maxGoodsNums;
                    dto.maxRecevieNums = item.maxRecevieNums;
                    dto.startTime = item.startTime;
                    dto.endTime = item.endTime;
                    dto.isEnable = item.isEnable;
                    dto.isExclusive = item.isExclusive;
                    dto.isAutoReceive = item.isAutoReceive;
                    dto.effectiveDays = item.effectiveDays;
                    dto.effectiveHours = item.effectiveHours;
                    dto.startStatus = status;

                    var condition = conditions.Find(p => p.promotionId == item.id);
                    if (condition != null && condition.parameters.Contains("goodsId"))
                    {
                        var parameters = (JObject)JsonConvert.DeserializeObject(condition.parameters);
                        var goodId = parameters["goodsId"].ObjectToInt(0);
                        var good = goodData.Find(p => p.id == goodId);
                        if (good != null)
                        {
                            dto.goodBrief = good.brief;
                            dto.goodName = good.name;
                            dto.goodThumbnail = good.image;
                            dto.goodImages = good.images;
                            dto.goodStock = good.stock;
                            dto.goodViewCount = good.viewCount;
                            dto.goodUnit = good.unit;
                            dto.mktPrice = good.mktprice;
                            dto.price = good.price;

                            TimeSpan ts = item.endTime.Subtract(dtNow);
                            dto.timestamp = (int)ts.TotalSeconds;
                        }
                    }


                    var result = results.Find(p => p.promotionId == item.id);

                    if (result != null)
                    {
                        JObject resultParameters = (JObject)JsonConvert.DeserializeObject(result.parameters);
                        decimal promotionAmount = 0;
                        {
                            var cartProducts = new CartProducts()
                            {
                                nums = 1,
                                products = new CoreCmsProducts()
                                {
                                    price = dto.price,
                                    amount = dto.price,
                                }
                            };

                            switch (result.code)
                            {
                                //指定商品减固定金额
                                case "GOODS_REDUCE":
                                    promotionAmount = _promotionResultServices.result_GOODS_REDUCE(resultParameters, cartProducts, item);
                                    break;
                                //指定商品打X折
                                case "GOODS_DISCOUNT":
                                    promotionAmount = _promotionResultServices.result_GOODS_DISCOUNT(resultParameters, cartProducts, item);
                                    break;
                                //指定商品一口价
                                case "GOODS_ONE_PRICE":
                                    promotionAmount = _promotionResultServices.result_GOODS_ONE_PRICE(resultParameters, cartProducts, item);
                                    break;
                                //指定商品每第几件减指定金额
                                case "GOODS_HALF_PRICE":
                                    //这个条件不在列表做处理
                                    promotionAmount = 0;
                                    break;
                            }
                        }
                        if (promotionAmount > 0)
                        {
                            dto.price = Math.Round(dto.price - promotionAmount, 2);
                        }
                    }

                    dtoData.Add(dto);
                }
            }
            jm.data = new
            {
                promotions.TotalCount,
                promotions.TotalPages,
                list = dtoData,
                pageIndex,
                pageSize
            };
            return jm;
        }

        #endregion

        #region 获取团购/秒杀商品详情
        /// <summary>
        /// 获取团购/秒杀商品详情
        /// </summary>
        /// <returns></returns>

        public async Task<WebApiCallBack> GetGroupDetail(int groupId, int userId, int type, bool needSku)
        {
            using var container = _serviceProvider.CreateScope();

            var goodsServices = container.ServiceProvider.GetService<ICoreCmsGoodsServices>();
            var orderServices = container.ServiceProvider.GetService<ICoreCmsOrderServices>();

            var jm = new WebApiCallBack() { msg = "关键参数丢失" };

            if (groupId == 0)
            {
                return jm;
            }

            var promotion = await _dal.QueryByClauseAsync(p => p.isDel == false && p.isEnable == true && p.id == groupId, true, true);
            if (promotion == null)
            {
                jm.msg = "无此活动";
                jm.otherData = groupId;
                return jm;
            }

            var goodId = 0;
            var condition = await _promotionConditionServices.QueryByClauseAsync(p => p.promotionId == groupId, true, true);
            if (condition != null)
            {
                var obj = (JObject)JsonConvert.DeserializeObject(condition.parameters);
                if (obj.ContainsKey("goodsId") && obj["goodsId"].ObjectToInt(0) > 0)
                {
                    goodId = obj["goodsId"].ObjectToInt(0);
                }
            }

            if (goodId == 0)
            {
                jm.msg = "未提交商品信息";
                jm.otherData = groupId;
                return jm;
            }

            string typeStr = type == (int)GlobalEnumVars.PromotionType.Group ? GlobalEnumVars.PromotionType.Group.ToString().ToLowerInvariant() : GlobalEnumVars.PromotionType.Seckill.ToString().ToLowerInvariant();

            var goods = await goodsServices.GetGoodsDetail(goodId, userId, true, typeStr, groupId, needSku);
            if (goods == null)
            {
                jm.msg = "商品不存在";
                return jm;
            }

            if (goods.isMarketable == false)
            {
                jm.msg = "商品已下架";
                return jm;
            }

            //调整前台显示数量
            var checkOrder = orderServices.FindLimitOrder(goods.product.id, userId, promotion.startTime, promotion.endTime, promotion.type);

            //如果最大为设置值
            if (promotion.maxGoodsNums > 0)
            {
                //最多只能买这么多
                goods.stock = promotion.maxGoodsNums;
                //然后实际能买的要减去以前买的
                goods.product.stock = checkOrder.TotalOrders - promotion.maxGoodsNums >= 0 ? 0 : promotion.maxGoodsNums - checkOrder.TotalOrders;
            }

            //如果设置了限购数量
            if (promotion.maxNums > 0)
            {
                //最多只能买这么多
                goods.stock = promotion.maxNums;
                //实际可购买数量为：实际消费数量-最大可消费数量，如果大于或者等于，就不能买了。库存为0，或最大购买数减去已经购买数
                goods.product.stock = checkOrder.TotalOrders - promotion.maxNums >= 0 ? 0 : promotion.maxNums - checkOrder.TotalOrders;
            }

            goods.buyPromotionCount = checkOrder.TotalOrders;

            var dt = DateTime.Now;

            goods.groupId = promotion.id;
            goods.groupType = promotion.type;
            goods.groupStatus = promotion.isEnable;
            goods.groupTime = dt;
            goods.groupStartTime = promotion.startTime;
            goods.groupEndTime = promotion.endTime;

            TimeSpan ts = promotion.endTime.Subtract(dt);
            goods.groupTimestamp = (int)ts.TotalSeconds;

            //获取规则结果集
            decimal promotionAmount = 0;
            var result = await _promotionResultServices.QueryByClauseAsync(p => p.promotionId == promotion.id);
            if (result != null)
            {
                JObject resultParameters = (JObject)JsonConvert.DeserializeObject(result.parameters);
                var cartProducts = new CartProducts()
                {
                    nums = 1,
                    products = new CoreCmsProducts()
                    {
                        price = goods.product.price,
                        amount = goods.product.price,
                    }
                };
                switch (result.code)
                {
                    //指定商品减固定金额
                    case "GOODS_REDUCE":
                        promotionAmount = _promotionResultServices.result_GOODS_REDUCE(resultParameters, cartProducts, promotion);
                        goods.groupPromotionResult = "指定商品减少固定金额：减" + resultParameters["money"].ObjectToString() + "元 ";
                        break;
                    //指定商品打X折
                    case "GOODS_DISCOUNT":
                        promotionAmount = _promotionResultServices.result_GOODS_DISCOUNT(resultParameters, cartProducts, promotion);
                        goods.groupPromotionResult = "指定商品打折：打" + resultParameters["discount"].ObjectToString() + "折 ";
                        break;
                    //指定商品一口价
                    case "GOODS_ONE_PRICE":
                        promotionAmount = _promotionResultServices.result_GOODS_ONE_PRICE(resultParameters, cartProducts, promotion);
                        goods.groupPromotionResult = "指定商品一口价：" + resultParameters["money"].ObjectToString() + "元 ";
                        break;
                    //指定商品每第几件减指定金额
                    case "GOODS_HALF_PRICE":
                        //这个条件不在列表做处理
                        promotionAmount = 0;
                        goods.groupPromotionResult = "指定商品每第" + resultParameters["num"].ObjectToString() + "件减少" + resultParameters["money"].ObjectToString() + "元";
                        break;
                    case "ORDER_REDUCE":
                        goods.groupPromotionResult = "订单减" + resultParameters["money"].ObjectToString() + "元 ";
                        break;
                    case "ORDER_DISCOUNT":
                        goods.groupPromotionResult = "订单打" + resultParameters["discount"].ObjectToString() + "折 ";
                        break;
                }

                foreach (var item in goods.skuList.sku_list)
                {
                    switch (result.code)
                    {
                        //指定商品减固定金额
                        case "GOODS_REDUCE":
                            var reoucePrice = resultParameters["money"].ObjectToDecimal(0);
                            item.price = Math.Round(item.price - reoucePrice, 2);
                            break;
                        //指定商品打X折
                        case "GOODS_DISCOUNT":
                            var objDiscount = resultParameters["discount"].ObjectToDecimal(0);
                            item.price = Math.Round(Math.Round(Math.Round(item.price * objDiscount, 3) * 10, 2) / 100, 2);
                            break;
                        //指定商品一口价
                        case "GOODS_ONE_PRICE":
                            var newPrice = resultParameters["money"].ObjectToDecimal(0);
                            item.price = Math.Round(newPrice, 2);
                            break;
                        default:
                            item.price = Math.Round(item.price - promotionAmount, 2);
                            break;
                    }
                }
            }
            if (promotionAmount > 0)
            {
                goods.product.price = Math.Round(goods.product.price - promotionAmount, 2);
            }




            //进行促销后要更换原销售价替换原市场价
            //var originPrice = Math.Round(goods.product.price + goods.product.promotionAmount, 2);
            //goods.product.mktprice = originPrice;
            jm.status = true;
            jm.msg = "数据获取成功";
            jm.data = goods;

            return jm;
        }

        #endregion

        #region 获取可领取的优惠券（不分页）
        /// <summary>
        /// 获取可领取的优惠券（不分页）
        /// </summary>
        /// <param name="limit">数量</param>
        /// <returns></returns>
        public async Task<List<CoreCmsPromotion>> ReceiveCouponList(int limit = 3)
        {
            var where = PredicateBuilder.True<CoreCmsPromotion>();
            where = where.And(p => p.endTime > DateTime.Now); //判断优惠券失效时间 是否可领取
            where = where.And(p => p.isEnable == true); //启用状态
            where = where.And(p => p.type == (int)GlobalEnumVars.PromotionType.Coupon);  //促销 类型
            where = where.And(p => p.isAutoReceive == true);  //自动领取状态
            where = where.And(p => p.isDel == false);  //是否被删除

            var data = await _dal.QueryPageAndChildsAsync(where, p => p.sort, OrderByType.Asc, false, 0, limit);

            if (data != null && data.Any())
            {
                foreach (var item in data)
                {

                    var expression1 = "";
                    var expression2 = "";

                    foreach (var condition in item.promotionCondition)
                    {
                        var str = PromotionHelper.GetConditionMsg(condition.code, condition.parameters);
                        expression1 += str;
                        item.conditions.Add(str);
                    }
                    foreach (var result in item.promotionResult)
                    {
                        var str = PromotionHelper.GetResultMsg(result.code, result.parameters);
                        expression2 += str;
                        item.results.Add(str);
                    }
                    item.expression1 = expression1;
                    item.expression2 = expression2;
                }
            }
            return data.ToList();
        }
        #endregion

        #region 获取可领取的优惠券（分页）

        /// <summary>
        /// 获取可领取的优惠券（分页）
        /// </summary>
        /// <param name="page">页码</param>
        /// <param name="limit">数量</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsPromotion>> GetReceiveCouponList(int page = 1, int limit = 10)
        {
            var where = PredicateBuilder.True<CoreCmsPromotion>();
            where = where.And(p => p.endTime > DateTime.Now); //判断优惠券失效时间 是否可领取
            where = where.And(p => p.isEnable == true); //启用状态
            where = where.And(p => p.type == (int)GlobalEnumVars.PromotionType.Coupon);  //促销 类型
            where = where.And(p => p.isAutoReceive == true);  //自动领取状态
            where = where.And(p => p.isDel == false);  //是否被删除

            var data = await _dal.QueryPageAndChildsAsync(where, p => p.sort, OrderByType.Asc, true, page, limit);

            if (data != null && data.Any())
            {
                foreach (var item in data)
                {
                    var expression1 = "";
                    var expression2 = "";
                    foreach (var condition in item.promotionCondition)
                    {
                        var str = PromotionHelper.GetConditionMsg(condition.code, condition.parameters);
                        expression1 += str;
                        item.conditions.Add(str);
                    }
                    foreach (var result in item.promotionResult)
                    {
                        var str = PromotionHelper.GetResultMsg(result.code, result.parameters);
                        expression2 += str;
                        item.results.Add(str);
                    }
                    item.expression1 = expression1;
                    item.expression2 = expression2;
                }
            }
            return data;
        }
        #endregion

        #region 获取指定id 的优惠券是否可以领取
        /// <summary>
        /// 获取指定id 的优惠券是否可以领取
        /// </summary>
        /// <param name="promotionId"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> ReceiveCoupon(int promotionId)
        {
            var jm = new WebApiCallBack();
            var dt = DateTime.Now;
            var where = PredicateBuilder.True<CoreCmsPromotion>();
            where = where.And(p => p.endTime > dt); //判断优惠券失效时间 是否可领取
            //where = where.And(p => p.startTime < dt); 
            where = where.And(p => p.isEnable == true); //启用状态
            where = where.And(p => p.type == (int)GlobalEnumVars.PromotionType.Coupon);  //促销 类型
            where = where.And(p => p.isAutoReceive == true);  //自动领取状态
            where = where.And(p => p.id == promotionId);
            where = where.And(p => p.isDel == false);  //是否被删除


            var info = await _dal.QueryByClauseAsync(where, false, true);
            if (info != null)
            {
                jm.data = info;
                //判断最大领取数量
                if (info.endTime < dt || info.startTime > dt)
                {
                    jm.status = false;
                    jm.msg = "请在领取时间范围内领取";
                    return jm;
                }
                if (info.maxRecevieNums == 0)
                {
                    jm.status = true;
                    return jm;
                }
                var receiveCount = await _couponServices.GetCountAsync(p => p.promotionId == promotionId);
                if (receiveCount >= info.maxRecevieNums)
                {
                    jm.status = false;
                    jm.msg = "该优惠券已被领完，请下次再来！";
                    return jm;
                }
                else
                {
                    jm.status = true;
                    jm.code = receiveCount;
                }

            }
            else
            {
                jm.msg = GlobalErrorCodeVars.Code15007;
            }
            return jm;
        }

        #endregion


        #region 获取全局促销列表

        /// <summary>
        /// 获取全局促销列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<GetPromotionResult>> GetPromotionList(int type = (int)GlobalEnumVars.PromotionType.Promotion)
        {
            var where = PredicateBuilder.True<CoreCmsPromotion>();
            var dt = DateTime.Now;
            where = where.And(p => p.startTime < dt); //判断优惠券失效时间 是否可领取
            where = where.And(p => p.endTime > dt); //判断优惠券失效时间 是否可领取
            where = where.And(p => p.isEnable); //启用状态
            where = where.And(p => p.type == type);  //促销类型
            where = where.And(p => !p.isDel);  //是否被删除

            var data = await _dal.QueryPageAndChildsAsync(where, p => p.sort, OrderByType.Asc, true, 1, 1000);

            if (data != null && data.Any())
            {
                var goodsServices = _serviceProvider.GetService<ICoreCmsGoodsServices>();
                var goodsCategoryServices = _serviceProvider.GetService<ICoreCmsGoodsCategoryServices>();
                var brandServices = _serviceProvider.GetService<ICoreCmsBrandServices>();
                var userGradeServices = _serviceProvider.GetService<ICoreCmsUserGradeServices>();

                foreach (var item in data)
                {
                    foreach (var condition in item.promotionCondition)
                    {
                        var obj = (JObject)JsonConvert.DeserializeObject(condition.parameters);
                        var str = string.Empty;

                        if (condition.code == "GOODS_ALL")
                        {
                            str = "购买任意商品：只要购买任意产品即可；";
                        }
                        //购买指定商品
                        else if (condition.code == "GOODS_IDS")
                        {
                            var goodsId = obj["goodsId"].ObjectToString();
                            if (!string.IsNullOrEmpty(goodsId))
                            {
                                str = "购买指定商品：";
                                var ids = goodsId.Split(",").Select(p => p.ObjectToInt()).ToList();
                                var goods = await goodsServices.QueryListByClauseAsync(p => ids.Contains(p.id), p => p.id, OrderByType.Asc, true);
                                if (goods.Any())
                                {
                                    var goodsName = goods.Select(p => p.name = "【" + p.name + "】").ToList();
                                    str += string.Join(",", goodsName);
                                }
                                str += "；购买数量：" + obj["nums"].ObjectToString();
                            }
                        }
                        //购买指定商品分类
                        else if (condition.code == "GOODS_CATS")
                        {
                            var id = obj["catId"].ObjectToInt(0);
                            if (id > 0)
                            {
                                str = "购买指定分类商品：";
                                var goodCache = await goodsCategoryServices.GetCaChe();
                                var goodsCategory = goodCache.FirstOrDefault(p => p.id == id);
                                str += goodsCategory != null ? "【" + goodsCategory.name + "】" : "";
                                str += "；购买数量：" + obj["nums"].ObjectToString();
                            }
                        }
                        //购买指定品牌商品
                        else if (condition.code == "GOODS_BRANDS")
                        {
                            var id = obj["brandId"].ObjectToInt(0);
                            if (id > 0)
                            {
                                str = "购买指定品牌商品：";
                                var brandCache = await brandServices.QueryAsync(true, true);
                                var brand = brandCache.FirstOrDefault(p => p.id == id);
                                str += brand != null ? "【" + brand.name + "】" : "";
                                str += "；购买数量：" + obj["nums"].ObjectToString();
                            }
                        }
                        //用户符合指定等级
                        else if (condition.code == "USER_GRADE")
                        {
                            var gradesId = obj["grades"].ObjectToString();
                            if (!string.IsNullOrEmpty(gradesId))
                            {
                                str = "用户符合指定等级：";
                                var ids = gradesId.Split(",").Select(p => p.ObjectToInt()).ToList();
                                var userGradesCache = await userGradeServices.QueryAsync(true, true);
                                var userGrades = userGradesCache.Where(p => ids.Contains(p.id));
                                if (userGrades.Any())
                                {
                                    var goodsName = userGrades.Select(p => p.title = "【" + p.title + "】").ToList();
                                    str += string.Join(",", goodsName);
                                }
                            }
                        }
                        else if (condition.code == "ORDER_FULL")
                        {
                            str = obj != null ? "购买订单满" + obj["money"].ObjectToString() + "元 " : "";
                        }

                        if (!string.IsNullOrEmpty(str))
                        {
                            item.conditions.Add(str);
                        }
                    }
                    foreach (var result in item.promotionResult)
                    {
                        //var str = PromotionHelper.GetResultMsg(result.code, result.parameters);
                        var msg = string.Empty;
                        var obj = (JObject)JsonConvert.DeserializeObject(result.parameters);

                        switch (result.code)
                        {
                            case "GOODS_REDUCE":
                                msg = "指定商品减少固定金额：减" + obj["money"].ObjectToString() + "元 ";
                                break;
                            case "GOODS_DISCOUNT":
                                msg = "指定商品打折：打" + obj["discount"].ObjectToString() + "折 ";
                                break;
                            case "GOODS_ONE_PRICE":
                                msg = "指定商品一口价：" + obj["money"].ObjectToString() + "元 ";
                                break;
                            case "ORDER_REDUCE":
                                msg = "订单减" + obj["money"].ObjectToString() + "元 ";
                                break;
                            case "ORDER_DISCOUNT":
                                msg = "订单打" + obj["discount"].ObjectToString() + "折 ";
                                break;
                            case "GOODS_HALF_PRICE":
                                msg = "指定商品每第" + obj["num"].ObjectToString() + "件减少" + obj["money"].ObjectToString() + "元";
                                break;
                        }

                        item.results.Add(msg);
                    }
                }
            }

            var list = new List<GetPromotionResult>();
            if (data.Any())
            {
                foreach (var item in data)
                {
                    var dto = new GetPromotionResult();
                    dto.id = item.id;
                    dto.name = item.name;
                    dto.type = item.type;
                    dto.sort = item.sort;
                    dto.maxNums = item.maxNums;
                    dto.maxGoodsNums = item.maxGoodsNums;
                    dto.maxRecevieNums = item.maxRecevieNums;
                    dto.startTime = item.startTime;
                    dto.endTime = item.endTime;
                    dto.isEnable = item.isEnable;
                    dto.isExclusive = item.isExclusive;
                    dto.isAutoReceive = item.isAutoReceive;
                    dto.effectiveDays = item.effectiveDays;
                    dto.effectiveHours = item.effectiveHours;
                    dto.conditions = item.conditions;
                    dto.results = item.results;
                    list.Add(dto);
                }
            }

            return list;
        }
        #endregion

    }
}
